package es.usc.citius.servando.calendula.settings.database;

import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.support.annotation.StringRes;
import android.support.v4.app.ActivityCompat;
import android.support.v7.preference.ListPreference;
import android.support.v7.preference.Preference;
import android.widget.Toast;

import java.util.Objects;

import es.usc.citius.servando.calendula.CalendulaActivity;
import es.usc.citius.servando.calendula.R;
import es.usc.citius.servando.calendula.drugdb.download.DownloadDatabaseHelper;
import es.usc.citius.servando.calendula.settings.CalendulaPrefsFragment;
import es.usc.citius.servando.calendula.util.LogUtil;
import es.usc.citius.servando.calendula.util.PermissionUtils;
import es.usc.citius.servando.calendula.util.PreferenceKeys;
import es.usc.citius.servando.calendula.util.PreferenceUtils;

public class DatabasePrefsFragment
        extends CalendulaPrefsFragment<DatabasePrefsContract.View, DatabasePrefsContract.Presenter>
        implements DatabasePrefsContract.View {
    private final String TAG = "DatabasePrefsFragment";
    private final int REQUEST_DL_PERMISSION = 938;

    @Override
    public int getFragmentTitle() {
        return R.string.pref_header_prescriptions;
    }

    @Override
    public DatabasePrefsContract.Presenter getPresenter() {
        return new DatabasePrefsPresenter(
                PreferenceUtils.getString(
                        PreferenceKeys.DRUGDB_CURRENT_DB,
                        getString(R.string.database_none_id)
                )
        );
    }

    private ListPreference getDbPref() {
        return (ListPreference) findPreference(getString(R.string.prefkey_drugdb_current_db));
    }

    private Preference getUpdateDBPref() {
        return findPreference(getString(R.string.prefkey_settings_database_update));
    }

    private String getNoneId() {
        return getString(R.string.database_none_id);
    }

    private String getSettingUpId() {
        return getString(R.string.database_setting_up_id);
    }

    @Override
    public void onCreatePreferences(Bundle bundle, String rootKey) {
        LogUtil.d(TAG, "onCreatePreferences() called");
        addPreferencesFromResource(R.xml.pref_database);

        // set listeners for our prefs
        getDbPref().setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
            @Override
            public boolean onPreferenceChange(Preference preference, Object newValue) {
                return getPresenter().selectNewDb((String) newValue);
            }
        });
        getUpdateDBPref().setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
            @Override
            public boolean onPreferenceClick(Preference preference) {
                getPresenter().checkDatabaseUpdate(getContext());
                return true;
            }
        });
    }

    /**
     * From [SharedPreferences.OnSharedPreferenceChangeListener]
     *
     * @see [CalendulaPrefsFragment]
     */
    @Override
    public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
        LogUtil.d(TAG, "onSharedPreferenceChanged: preference $key changed");
        if (key.equals(getDbPref().getKey())) {
            getPresenter().currentDbUpdated(
                    PreferenceUtils.getString(
                            PreferenceKeys.DRUGDB_CURRENT_DB,
                            getNoneId()
                    )
            );
        }
    }

    @Override
    public void setDbList(String[] dbIds, String[] dbDisplayNames) {
        ListPreference dbPref = getDbPref();
        dbPref.setEntryValues(dbIds);
        dbPref.setEntries(dbDisplayNames);
        refreshUi();
    }

    @Override
    public String resolveString(@StringRes int stringRes) {
        return getContext().getString(stringRes);
    }

    @Override
    public void showSelectedDb(String dbId) {
        getDbPref().setValue(dbId);
        refreshUi();
    }

    @Override
    public void showDatabaseDownloadChoice(String dbId) {
        DownloadDatabaseHelper.instance()
                .showDownloadDialog(Objects.requireNonNull(getActivity()), dbId,
                        new DownloadDatabaseHelper.DownloadDatabaseDialogCallback() {
                            @Override
                            public void onDownloadAcceptedOrCancelled(boolean accepted) {
                                getPresenter().onDbDownloadChoiceResult(accepted);
                            }
                        });
    }

    @Override
    public void showDatabaseUpdateNotAvailable() {
        Toast.makeText(getContext(), R.string.database_update_not_available, Toast.LENGTH_SHORT).show();
    }

    @Override
    public Intent getIntent() {
        return Objects.requireNonNull(getActivity()).getIntent();
    }

    @Override
    public void openDatabaseSelection() {
        getPreferenceManager().showDialog(getDbPref());
    }


    @Override
    public void askForDownloadPermission(final String dbId) {
        if (!hasDownloadPermission()) {
            ((CalendulaActivity) getActivity()).requestPermission(new PermissionUtils.PermissionRequest() {
                @Override
                public int reqCode() {
                    return REQUEST_DL_PERMISSION;
                }

                @Override
                public String[] permissions() {
                    return new String[]{android.Manifest.permission.WRITE_EXTERNAL_STORAGE};
                }

                @Override
                public void onPermissionGranted() {
                    LogUtil.d(TAG, "onPermissionGranted() called");
                    getPresenter().onDownloadPermissionGranted(dbId);
                }

                @Override
                public void onPermissionDenied() {
                    LogUtil.d(TAG, "onPermissionDenied: permission denied");
                }
            });
        } else {
            throw new IllegalStateException("Permissions already granted!");
        }
    }

    @Override
    public boolean hasDownloadPermission() {
        boolean hasPermission = ActivityCompat.checkSelfPermission(
                Objects.requireNonNull(getContext()),
                android.Manifest.permission.WRITE_EXTERNAL_STORAGE
        ) == PackageManager.PERMISSION_GRANTED;
        LogUtil.d(TAG, "hasDownloadPermission: result is $hasPermission");
        return hasPermission;
    }

    private void refreshUi() {
        LogUtil.d(TAG, "refreshUi() called");
        ListPreference dbPref = getDbPref();
        if (dbPref.getValue().equals(getSettingUpId())) {
            dbPref.setSummary(getString(R.string.database_setting_up));
            dbPref.setEnabled(false);
        } else {
            dbPref.setSummary(dbPref.getEntry());
            dbPref.setEnabled(true);
        }

        getUpdateDBPref().setEnabled(dbPref.isEnabled() && !dbPref.getValue().equals(getNoneId()));
    }
}
